/*
 * Copyright (c) 2005-2018. YingQi Anime Technology Co. Ltd. All rights reserved.
 * FileName: DateUtils.java
 * Author:   LL
 * Date:     2018年3月21日 下午4:32:51
 * Description: //模块目的、功能描述
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.sfang.common.util.date;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 时间相关工具<br>
 * 〈功能详细描述〉
 *
 * @author LL
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class DateUtils {

    /**
     * 格式缓存
     */
    private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();

    public static final String PATTERN_Mmillisecond = "yyyy-MM-dd HH:mm:ss.SSS";

    public static final String PATTERN_Second = "yyyy-MM-dd HH:mm:ss";


    public static SimpleDateFormat FORMAT_Asian = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    static {
        FORMAT_Asian.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 北京
    }

    /**
     * 功能描述: <br>
     * Date转换为格式化时间
     *
     * @param date
     * @param pattern 格式
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String format(Date date, String pattern) {
        if (date == null)
            date = new Date();
        return format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), pattern);
    }

    public static Date formatAsianDate(Date date) {
        return parseDate(FORMAT_Asian.format(date));
    }

    public static String format(Date date) {
        String value = "";
        try {
            value = format(date, PATTERN_Mmillisecond);
        } catch (Exception e) {
            try {
                value = format(date, PATTERN_Second);
            } catch (Exception e1) {
                value = format(new Date(), PATTERN_Second);
            }
        }

        return value;
    }

    /**
     * 功能描述: <br>
     * localDateTime转换为格式化时间
     *
     * @param localDateTime
     * @param pattern       格式
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String format(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return localDateTime.format(formatter);
    }

    /**
     * 功能描述: <br>
     * 格式化字符串转为Date
     *
     * @param time 格式化时间
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Date parseDate(String time) {


        if (StringUtils.isBlank(time)) {
            return new Date();
        }
        Date date = null;
        try {
            date = new SimpleDateFormat(PATTERN_Mmillisecond).parse(time);
        } catch (Exception e) {
            try {
                date = new SimpleDateFormat(PATTERN_Second).parse(time);
            } catch (Exception e1) {
                date = new Date();
            }
        }

        return date;
    }

    public static String parseDateReturnString(String time) {

        Date date = null;

        if (StringUtils.isBlank(time)) {
            date = new Date();
        }

        try {
            date = new SimpleDateFormat(PATTERN_Mmillisecond).parse(time);
        } catch (Exception e) {
            try {
                date = new SimpleDateFormat(PATTERN_Second).parse(time);
            } catch (Exception e1) {
                date = new Date();
            }
        }

        String rlt = format(date, PATTERN_Mmillisecond);
        return rlt;
    }

    /**
     * 功能描述: <br>
     * 格式化字符串转为LocalDateTime
     *
     * @param time    格式化时间
     * @param pattern 格式
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static LocalDateTime parseLocalDateTime(String time, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return LocalDateTime.parse(time, formatter);
    }

    /**
     * 功能描述: <br>
     * 减少天数
     *
     * @param date
     * @param days
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Date minusDays(Date date, long days) {
        LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(ldt.minusDays(days).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 功能描述: <br>
     * 减少月份
     *
     * @param date
     * @param months
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Date minusMonths(Date date, int months) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MONTH,-months);
        return rightNow.getTime();
    }

    /**
     * 功能描述: <br>
     * 增加天数
     *
     * @param date
     * @param daysToAdd
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Date plusDays(Date date, long daysToAdd) {
        LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(ldt.plusDays(daysToAdd).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 功能描述: <br>
     * 增加月份
     *
     * @param date
     * @param monthsToAdd
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Date plusMonths(Date date, long monthsToAdd) {
        LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(ldt.plusMonths(monthsToAdd).atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date plusMins(Date date, long minsToAdd) {
        LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return Date.from(ldt.plusMinutes(minsToAdd).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 功能描述: <br>
     * 在缓存中创建DateTimeFormatter
     *
     * @param pattern 格式
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private static DateTimeFormatter createCacheFormatter(String pattern) {
        if (StringUtils.isBlank(pattern)) {
            throw new IllegalArgumentException("Invalid pattern specification");
        }

        DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern);
        if (formatter == null) {
            formatter = DateTimeFormatter.ofPattern(pattern);
            FORMATTER_CACHE.put(pattern, formatter);
        }

        return formatter;
    }


    /**
     * 计算两个日期之间相差的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int daysBetween(Date date1, Date date2) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * String类型转换成Date日期类型
     *
     * @param source
     * @return
     */
    public static Date strToDate(String source) {
        try {
            long lt = new Long(source);
            Date date = new Date(lt);
            return date;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * String类型转换成Date日期类型
     *
     * @param source
     * @return
     */
    public static Date strToDate(String source, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);//设置时间格式
        Date ts=null;//创建Date对象
        try {
            ts = sdf.parse(source);//转换为Date类型 这里要抛一个异常
        } catch (ParseException e) {

            e.printStackTrace();
        }
        return ts;
    }

    public static Date firstDayOfMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        // 获取前月的第一天
        Calendar cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        String firstday = format.format(cale.getTime());

        try {
            return format.parse(firstday);
        } catch (ParseException e) {
            return new Date();
        }
    }

    public static Date lastDayOfMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        String lastday = format.format(cale.getTime());

        try {
            return format.parse(lastday);
        } catch (ParseException e) {
            return new Date();
        }
    }
}
